import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Activity } from './entities/activity.entity';
import { CreateActivityDto } from './dto/create-activity.dto';
import { User } from '../user/entities/user.entity';
import { ActivityFavorite } from './entities/activity-favorite.entity';
import { 
  MoreThan, 
  LessThan, 
  LessThanOrEqual, 
  MoreThanOrEqual, 
  Between 
} from 'typeorm';

export type ActivityStatus = 'upcoming' | 'ongoing' | 'finished';

@Injectable()
export class ActivityService {
  constructor(
    @InjectRepository(Activity)
    private readonly activityRepository: Repository<Activity>,
    @InjectRepository(ActivityFavorite)
    private readonly activityFavoriteRepository: Repository<ActivityFavorite>,
  ) {}

  // 添加 getter 方法
  public getRepository(): Repository<Activity> {
    return this.activityRepository;
  }

  async create(userId: number, createActivityDto: CreateActivityDto): Promise<Activity> {
    // 验证开始时间和结束时间
    const startTime = new Date(createActivityDto.startTime);
    const endTime = new Date(createActivityDto.endTime);
    const now = new Date();

    if (startTime < now) {
      throw new BadRequestException('活动开始时间不能早于当前时间');
    }

    if (endTime <= startTime) {
      throw new BadRequestException('活动结束时间必须晚于开始时间');
    }

    // 验证最小参与人数和最大参与人数
    if (createActivityDto.minParticipants > createActivityDto.maxParticipants) {
      throw new BadRequestException('最小参与人数不能大于最大参与人数');
    }

    // 创建新活动
    const activity = this.activityRepository.create({
      ...createActivityDto,
      creatorId: userId,
      currentParticipants: 0,
    });

    return this.activityRepository.save(activity);
  }

  async findAll(page: number = 1, pageSize: number = 10, status?: 'upcoming' | 'ongoing' | 'finished') {
    const now = new Date();
    let whereCondition: any = {};

    if (status) {
      switch (status) {
        case 'upcoming':
          whereCondition = { startTime: MoreThan(now) };
          break;
        case 'ongoing':
          whereCondition = {
            startTime: LessThanOrEqual(now),
            endTime: MoreThanOrEqual(now)
          };
          break;
        case 'finished':
          whereCondition = { endTime: LessThan(now) };
          break;
      }
    }

    const [list, total] = await this.activityRepository.findAndCount({
      where: whereCondition,
      relations: ['creator'],
      order: { createdAt: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return {
      list,  // 改为 list
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  async findOne(id: number): Promise<Activity> {
    const activity = await this.activityRepository.findOne({
      where: { id },
      relations: ['creator']
    });

    if (!activity) {
      throw new NotFoundException(`Activity with ID ${id} not found`);
    }

    // 使用 TypeORM 的方式更新 viewCount
    await this.activityRepository.increment(
      { id },
      'viewCount',
      1
    );

    // 重新获取更新后的活动数据
    return this.activityRepository.findOne({
      where: { id },
      relations: ['creator']
    });
  }

  async findByCreator(userId: number, page: number = 1, pageSize: number = 10) {
    const [list, total] = await this.activityRepository.findAndCount({
      where: { creatorId: userId },
      order: { createdAt: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return {
      list,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  async findByParticipant(userId: number, page: number = 1, pageSize: number = 10) {
    const [list, total] = await this.activityRepository
      .createQueryBuilder('activity')
      .leftJoinAndSelect('activity.creator', 'creator')
      .innerJoin('activity_participants', 'ap', 'ap.activity_id = activity.id')
      .where('ap.user_id = :userId', { userId })
      .orderBy('activity.createdAt', 'DESC')
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    return {
      list,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  async joinActivity(activityId: number, userId: number) {
    const activity = await this.activityRepository.findOne({
      where: { id: activityId },
      relations: ['participants']
    });

    if (!activity) {
      throw new NotFoundException('Activity not found');
    }

    if (!activity.participants) {
      activity.participants = [];
    }

    activity.participants.push({ id: userId } as User);
    activity.currentParticipants += 1;

    return this.activityRepository.save(activity);
  }

  async leaveActivity(activityId: number, userId: number) {
    const activity = await this.activityRepository.findOne({
      where: { id: activityId },
      relations: ['participants']
    });

    if (!activity) {
      throw new NotFoundException('Activity not found');
    }

    activity.participants = activity.participants.filter(p => p.id !== userId);
    activity.currentParticipants -= 1;

    return this.activityRepository.save(activity);
  }

  async getActivityStatusStats() {
    const now = new Date();

    const upcoming = await this.activityRepository.count({
      where: { startTime: MoreThan(now) }
    });

    const ongoing = await this.activityRepository.count({
      where: {
        startTime: LessThanOrEqual(now),
        endTime: MoreThanOrEqual(now)
      }
    });

    const finished = await this.activityRepository.count({
      where: { endTime: LessThan(now) }
    });

    return {
      upcoming,
      ongoing,
      finished,
      total: upcoming + ongoing + finished,
      currentTime: now
    };
  }

  async checkFavoriteStatus(activityId: number, userId: number): Promise<boolean> {
    const favorite = await this.activityFavoriteRepository.findOne({
      where: {
        activityId,
        userId,
      },
    });
    return !!favorite;
  }

  async favoriteActivity(activityId: number, userId: number): Promise<void> {
    const activity = await this.activityRepository.findOne({
      where: { id: activityId },
    });

    if (!activity) {
      throw new NotFoundException('Activity not found');
    }

    const existingFavorite = await this.activityFavoriteRepository.findOne({
      where: {
        activityId,
        userId,
      },
    });

    if (existingFavorite) {
      throw new BadRequestException('Activity already favorited');
    }

    const favorite = this.activityFavoriteRepository.create({
      activityId,
      userId,
    });

    await this.activityFavoriteRepository.save(favorite);

    // 更新收藏数
    await this.activityRepository.increment({ id: activityId }, 'favoriteCount', 1);
  }

  async unfavoriteActivity(activityId: number, userId: number): Promise<void> {
    const favorite = await this.activityFavoriteRepository.findOne({
      where: {
        activityId,
        userId,
      },
    });

    if (!favorite) {
      throw new BadRequestException('Activity not favorited');
    }

    await this.activityFavoriteRepository.remove(favorite);

    // 更新收藏数
    await this.activityRepository.decrement({ id: activityId }, 'favoriteCount', 1);
  }

  async getUserFavorites(userId: number, page: number = 1, pageSize: number = 10) {
    const [items, total] = await this.activityFavoriteRepository
      .createQueryBuilder('favorite')
      .leftJoinAndSelect('favorite.activity', 'activity')
      .leftJoinAndSelect('activity.creator', 'creator')
      .where('favorite.userId = :userId', { userId })
      .orderBy('favorite.createdAt', 'DESC')
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    return {
      items: items.map(item => item.activity),
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  async checkJoinStatus(activityId: number, userId: number): Promise<boolean> {
    try {
      const activity = await this.activityRepository.findOne({
        where: { id: activityId },
        relations: ['participants']
      });

      if (!activity) {
        throw new NotFoundException(`Activity with ID ${activityId} not found`);
      }

      if (!activity.participants) {
        return false;
      }

      return activity.participants.some(participant => participant.id === userId);
    } catch (error) {
      console.error(`Error checking join status for activity ${activityId} and user ${userId}:`, error);
      throw error;
    }
  }
}



















